From 8c626737aaf62433b59acfc3c1fa3688ecf278b2 Mon Sep 17 00:00:00 2001 From: Christoph Egger Date: Fri, 1 Jul 2011 20:48:00 +0100 Subject: [PATCH] nestedsvm: fix handling of invalid virtual vmcb When the l1 guest sets up an invalid vmcb then inject VMEXIT(#INVALID) rather having the host sitting in an endless loop of injecting #UD. Signed-off-by: Christoph Egger --- xen/arch/x86/hvm/svm/nestedsvm.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/hvm/svm/nestedsvm.c b/xen/arch/x86/hvm/svm/nestedsvm.c index 8de07e16d0..cb5e1a31eb 100644 --- a/xen/arch/x86/hvm/svm/nestedsvm.c +++ b/xen/arch/x86/hvm/svm/nestedsvm.c @@ -28,6 +28,10 @@ #include /* for local_event_delivery_(en|dis)able */ #include /* p2m_get_pagetable, p2m_get_nestedp2m */ + +#define NSVM_ERROR_VVMCB 1 +#define NSVM_ERROR_VMENTRY 2 + static void nestedsvm_vcpu_clgi(struct vcpu *v) { @@ -616,13 +620,13 @@ static int nsvm_vmcb_prepare4vmrun(struct vcpu *v, struct cpu_user_regs *regs) rc = svm_vmcb_isvalid(__func__, ns_vmcb, 1); if (rc) { gdprintk(XENLOG_ERR, "virtual vmcb invalid\n"); - return rc; + return NSVM_ERROR_VVMCB; } rc = svm_vmcb_isvalid(__func__, n2vmcb, 1); if (rc) { gdprintk(XENLOG_ERR, "n2vmcb invalid\n"); - return rc; + return NSVM_ERROR_VMENTRY; } /* Switch guest registers to l2 guest */ @@ -718,7 +722,15 @@ nsvm_vcpu_vmrun(struct vcpu *v, struct cpu_user_regs *regs) * and l1 guest keeps alive. */ nestedhvm_vcpu_enter_guestmode(v); - if (ret) { + switch (ret) { + case 0: + break; + case NSVM_ERROR_VVMCB: + gdprintk(XENLOG_ERR, "inject VMEXIT(INVALID)\n"); + svm->ns_vmexit.exitcode = VMEXIT_INVALID; + return -1; + case NSVM_ERROR_VMENTRY: + default: gdprintk(XENLOG_ERR, "nsvm_vcpu_vmentry failed, injecting #UD\n"); hvm_inject_exception(TRAP_invalid_op, HVM_DELIVER_NO_ERROR_CODE, 0); -- 2.30.2